package com.一致性Hash;

import net.minidev.json.JSONValue;

import java.util.*;
/**
 * @author: LCG
 * @date: 2022-06-06 23:49:17
 * @description: 测试实现一致性Hash
 **/
public class Test一致性Hash {

    private  List<String> real=new ArrayList<>();

    private  Map<String,String>  vHostToRealHost=new HashMap<>();

    /** key是虚拟节点的hash值，value是物理节点 **/
    private  SortedMap<Long,String> sortedMap=new TreeMap<>();

    private  int vHostNum=100;

    public static void main(String[] args) {

        Test一致性Hash testHash=new Test一致性Hash();

        testHash.addService("192.168.137.1");
        testHash.addService("192.168.137.2");
        testHash.addService("192.168.137.3");

        HashMap<String,Integer> hashMap=new HashMap<>();

        for (int i =0;i<1;i++){

            String service = testHash.getService("a" + i);
            System.out.println("a"+i+" 对应的服务器："+service);

            if(hashMap.containsKey(service)){
                hashMap.put(service,hashMap.get(service)+1);
            }else{
                hashMap.put(service,1);
            }

        }

        System.out.println("01==>"+JSONValue.toJSONString(hashMap));


        //testHash.removeService("192.168.137.1");
/*        testHash.addService("192.168.137.4");
        testHash.addService("192.168.137.5");
        HashMap<String,Integer> hashMap2=new HashMap<>();
        for (int i =0;i<100000;i++){

            String service = testHash.getService("a" + i);
            //System.out.println("a"+i+" 对应的服务器02："+service);

            if(hashMap2.containsKey(service)){
                hashMap2.put(service,hashMap2.get(service)+1);
            }else{
                hashMap2.put(service,1);
            }

        }

        System.out.println("02==>"+JSONValue.toJSONString(hashMap2));*/

    }

    /** 添加一个节点 **/
    public void addService(String node){

        String vnode=null;

        for(int i=0;i<vHostNum;i++){

            vnode=node+"-"+i;

            long i1 =(long) FNV1_32_HASH(vnode);

            if(!sortedMap.containsKey(i1)){
                //维护排序Map的key
                sortedMap.put(i1,node);
            }

            if(!vHostToRealHost.containsKey(vnode)){
                //存储虚拟节点和真实节点的映射关系
                vHostToRealHost.put(vnode,node);
            }

        }

        //添加到物理节点的列表
        real.add(node);
    }


    /** 获取一个节点 **/
    public String getService(String key){

        long hash = FNV1_32_HASH(key);

        //sortedMap.tailMap 意思是取出  大于等于 给定的key的集合
        SortedMap<Long, String> longStringSortedMap = sortedMap.tailMap(hash);

        //System.out.println(hash+"----"+JSONValue.toJSONString(longStringSortedMap)+"==="+sortedMap.firstKey());

        if(longStringSortedMap.isEmpty()){
            //如果是空的 就取出 sortedMap中的第一个key的value返回
            return sortedMap.get(sortedMap.firstKey());
        }else{
            return  longStringSortedMap.get(longStringSortedMap.firstKey());
        }

    }

    /** 删除物理节点 **/
    public void removeService(String node){
        Set<Map.Entry<Long, String>> entries = sortedMap.entrySet();
        List<Long> keys=new ArrayList<>();
        entries.forEach(entry->{
            if(entry.getValue().equals(node)){
                keys.add(entry.getKey());
            }
        });

        System.out.println("====keys==========>"+keys.size());

        for (int i = 0; i < keys.size(); i++) {
            sortedMap.remove(keys.get(i));
        }

    }



    private static long FNV1_32_HASH(String str) {
        final int p = 16777619;
        int hash = (int) 2166136261L;
        for (int i = 0; i < str.length(); i++){
            hash = (hash ^ str.charAt(i)) * p;
        }

        hash += hash << 13;
        hash ^= hash >> 7;
        hash += hash << 3;
        hash ^= hash >> 17;
        hash += hash << 5;

        // 如果算出来的值为负数则取其绝对值
        if (hash < 0){
            hash = Math.abs(hash);
        }

        return (long)hash;
    }

}
